/**
 * node-item 对应每一个组件
 * node-cell 对组件进行列分组
 */

(function (win, $) {
    //常量
    var MOD_NAME = 'workflow'
        , TOOLTIP = [
        '<div id="addtooltip-warpper">'
        , '<div id="addtooltip-box">'
        , '<div>'
        , '<div class="item-wrapper" data-addType="verify">'
        , '<span>审核</span>'
        , '</div>'
        , '<p class="item-user">审核人</p>'
        , '</div>'
        , '<div>'
        , '<div class="item-wrapper" data-addType="cc">'
        , '<span>抄送</span>'
        , '</div>'
        , '<p class="item-user">抄送人</p>'
        , '</div>'
        , '<div>'
        , '<div class="item-wrapper" data-addType="branch">'
        , '<span>分支</span>'
        , '</div>'
        , '<p class="item-user">条件分支</p>'
        , '</div>'
        , '</div>'
        , '<div id="addtooltip-pointer"></div>'
        , '</div>'
    ].join('')
        , CONDITIONFIRST = [
        '<div class="top-left-cover-line"></div>'
        , '<div class="bottom-left-cover-line"></div>'
    ].join('')
        , CONDITIONLAST = [
        '<div class="top-right-cover-line"></div>'
        , '<div class="bottom-right-cover-line"></div>'
    ].join('');

    //函数
    var styleInject = function (css, elem) {
        if (!css || typeof document === 'undefined') {
            return;
        }

        var head = elem ? elem : document.getElementsByTagName('head')[0];
        var style = document.createElement('style');
        style.type = 'text/css';

        if (head.firstChild) {
            head.insertBefore(style, head.firstChild);
        } else {
            head.appendChild(style);
        }

        if (style.styleSheet) {
            style.styleSheet.cssText = css;
        } else {
            style.appendChild(document.createTextNode(css));
        }
    };

    var css = '.node-item{position:relative}.node-wrap{display:inline-flex;flex-direction:column;align-items:center;width:100%;position:relative}.btnCopy{position:absolute;top:8px;right:25px;display:none;background-color:#ffffff;font-style:normal}.btnRemove{position:absolute;top:8px;right:8px;display:none;font-style:normal}.node-wrap-box{width:220px;min-height:78px;display:inline-flex;align-items:center;flex-direction:column;background-color:#FFFFFF;border-radius:5px;box-shadow:0 2px 5px 0 rgba(0,0,0,.1);cursor:pointer;border:1px solid #F5F5F5;position:relative}.node-wrap-box:hover{border:1px solid rgb(50,150,250);transition:all .3s}.node-wrap-box::before{content:"";position:absolute;top:-13px;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%);width:0;height:0;border-style:solid;border-width:8px 6px 4px;border-color:#cacaca transparent transparent;background:#f5f5f7}.start-node .node-wrap-box::before{display:none}.node-wrap-box .btnRemove{}.node-wrap-box:hover .btnRemove{display:block}.node-wrap-box .title{border-radius:4px 5px 0 0;box-sizing:border-box;height:30px}.node-wrap-box>div{width:100%}.node-wrap-box>div:nth-of-type(1){padding:5px 10px;color:white;font-size:12px;position:relative;box-sizing:border-box}.node-wrap-box>div:nth-of-type(2){padding:15px 10px;box-sizing:border-box;position:relative}.node-wrap-box>div:nth-of-type(2)>span{display:block;color:#666666;font-size:14px;box-sizing:border-box;padding-right:20px}.node-wrap-box>div:nth-of-type(2)>i{font-style:normal;color:#666666;font-size:14px;position:absolute;top:50%;right:10px;margin-top:-10px}.node-add-btn-box{position:relative}.node-add-btn-box::before{content:"";position:absolute;top:0;left:0;right:0;bottom:0;z-index:0;margin:auto;width:2px;height:100%;background-color:#cacaca}.add-node-btn{position:relative;z-index:1;padding:30px 0}.top-left-cover-line{position:absolute;height:3px;width:50%;background-color:#f5f5f7;top:-2px;left:-1px}.bottom-left-cover-line{position:absolute;height:3px;width:50%;background-color:#f5f5f7;bottom:-2px;left:-1px}.top-right-cover-line{position:absolute;height:3px;width:50%;background-color:#f5f5f7;top:-2px;right:-1px}.bottom-right-cover-line{position:absolute;height:3px;width:50%;background-color:#f5f5f7;bottom:-2px;right:-1px}.add-node-btn button{border-radius:50%;background:rgb(50,150,250);font-size:32px;border:none;width:40px;height:40px;line-height:40px;color:#ffffff;padding:0;margin:0;cursor:pointer}.branch-box-wrap{display:inline-flex;flex-direction:column;align-items:center;width:100%}.branch-box{display:flex;border-bottom:2px solid #cccccc;border-top:2px solid #cccccc;position:relative}.add-branch{position:absolute;display:inline-block;left:50%;top:-15px;z-index:1;border-radius:15px;color:rgb(50,150,250);border:none;box-shadow:0 2px 5px 0 rgba(0,0,0,.1);background:#FFFFFF;padding:5px 10px;font-size:12px;cursor:pointer;line-height:20px;transform:translateX(-50%)}.col-box{display:inline-flex;background:#f5f5f7;flex-direction:column;align-items:center;position:relative}.col-box::before{content:"";position:absolute;top:0;left:0;right:0;bottom:0;z-index:0;margin:auto;width:2px;height:100%;background-color:#cacaca}.condition-node-box{display:inline-flex;flex-direction:column;align-items:center;position:relative;padding:30px 50px 0 50px}.auto-judge{background-color:#FFFFFF;border-radius:5px;width:220px;position:relative;box-shadow:0 2px 5px 0 rgba(0,0,0,.1);cursor:pointer;border:1px solid #FFFFFF}.auto-judge:hover{border:1px solid rgb(50,150,250);transition:all .3s}.title-wrapper{padding:5px 0;background-color:#ffffff;border-radius:5px 5px 0 0;font-size:12px;position:relative;overflow:hidden}.title-wrapper span{display:block;padding:5px;box-sizing:border-box}.title-wrapper .condition-name{float:left;width:140px}.title-wrapper .condition-level{float:right;color:#15bc83;width:60px;margin-right:20px}.auto-judge:hover .btnCopy{display:block}.auto-judge:hover .btnRemove{display:block}.auto-judge>div:nth-of-type(2){padding:15px 10px;color:#666666;font-size:14px;box-sizing:border-box}.condition-node-box::before{content:"";position:absolute;top:0;left:0;right:0;bottom:0;margin:auto;width:2px;height:100%;background-color:#cacaca}.condition-input{line-height:19px;height:18px;display:inline-block;width:135px;padding:0;padding-left:5px;font-size:12px;border:none}.end-node{border-radius:50%;font-size:14px;color:rgba(25,31,37,.4);text-align:left}.end-node-circle{width:10px;height:10px;margin:auto;border-radius:50%;background:#dbdcdc}.end-node-text{margin-top:5px;text-align:center}.contene-open-choose{display:flex;justify-content:space-between;align-items:center;padding:10px 15px}.add-node-btn-box::before{content:"";position:absolute;top:0;left:0;right:0;bottom:0;z-index:-1;margin:auto;width:2px;height:100%;background-color:#cacaca}.item-wrapper{cursor:pointer;border:1px solid #e2e2e2;border-radius:50%;font-size:20px;text-align:center;line-height:60px;width:60px;height:60px;margin:0 auto}.item-wrapper:hover{border-color:rgb(50,150,250);transition:all .3s}.item-user{padding:0;margin:0;padding-top:5px;font-size:14px;color:#666666}#addtooltip-box{overflow:hidden}#addtooltip-box>div:nth-of-type(1) span{color:#ff943e}#addtooltip-box>div:nth-of-type(2) span{color:#3296fa}#addtooltip-box>div:nth-of-type(3) span{color:#15bc83}#addtooltip-box>div{float:left;padding:10px;text-align:center}#addtooltip-warpper{z-index:999;display:none;position:absolute;background:#FFFFFF;border:1px solid #EBEEF5;border-radius:5px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);width:248px}#addtooltip-pointer::after{content:"";border:8px solid transparent;border-right-color:#FFFFFF;position:absolute;left:-17px;top:20px}';

    styleInject(css);

    //类方法
    String.prototype.format = function (args) {
        var result = this;
        if (arguments.length > 0) {
            if (arguments.length == 1 && typeof (args) == "object") {
                for (var key in args) {
                    if (args[key] != undefined) {
                        var reg = new RegExp("({" + key + "})", "g");
                        result = result.replace(reg, args[key]);
                    }
                }
            } else {
                for (var i = 0; i < arguments.length; i++) {
                    if (arguments[i] != undefined) {
                        var reg = new RegExp("({[" + i + "]})", "g");
                        result = result.replace(reg, arguments[i]);
                    }
                }
            }
        }
        return result;
    };

    Array.prototype.remove = function (val) {
        var index = -1;
        for (var i = 0; i < this.length; i++) {
            if (this[i] == val) {
                index = i;
                break;
            }
        }

        if (index > -1) {
            this.splice(index, 1);
        }
    };

    //外部接口
    var Class = function (options) {
        var that = this;
        that.config = $.extend({}, that.config, options);
    };

    //默认配置
    Class.prototype.config = {
        elem: ""
        , data: {
            1: {
                key: 1,
                type: 'start',
                name: '发起人',
                content: '请设置发起人',
            },
            2: {
                key: 2,
                type: 'end',
                name: '结束流程',
            },
        }
        , line: {
            1: {
                prev: 0,
                current: 1,
                next: 2,
            },
            2: {
                prev: 1,
                current: 2,
                next: 0,
            },
        }
        , click: null
        , change: null
    };

    //组件定义
    Class.prototype.components = {
        start: {
            field: {
                key: -1,
                type: 'start',
                name: '发起人',
                content: '请设置发起人',
            }
            , render: function (json) {
                var _html = '';

                _html += '<div class="node-cell node-item node-wrap start-node" data-key="{0}">'.format(json.key);

                _html += '<div class="node-box node-wrap-box">';

                _html += '<div class="title" style="background: rgb(87, 106, 149);">';

                _html += '<span>{0}</span>'.format(json.name);

                _html += '</div>';

                _html += '<div>';

                _html += '<span>{0}</span>'.format(json.content);

                _html += '<i>&gt;</i>';

                _html += '</div>';

                _html += '</div>';

                _html += '<div class="node-add-btn-box">';

                _html += '<div class="add-node-btn">';

                _html += '<button class="addNodeClick">+</button>';

                _html += '</div>';

                _html += '</div>';

                _html += '</div>';

                return _html;
            }
        },
        verify: {
            field: {
                key: -1,
                type: 'verify',
                name: '审核人',
                content: '请设置审核人',
            }
            , render: function (json) {
                var _html = '';

                _html += '<div class="node-cell node-item node-wrap" data-key="{0}">'.format(json.key);

                _html += '<div class="node-box node-wrap-box start-node">';

                _html += '<div class="title" style="background: rgb(255, 148, 62);">';
                _html += '<span>{0}</span>'.format(json.name);
                _html += '<i class="btnRemove" title="删除">X</i>';
                _html += '</div>';
                _html += '<div>';
                _html += '<span>{0}</span>'.format(json.content);
                _html += '<i>&gt;</i>';
                _html += '</div>';
                _html += '</div>';
                _html += '<div class="node-add-btn-box">';
                _html += '<div class="add-node-btn">';
                _html += '<button class="addNodeClick">+</button>';
                _html += '</div>';
                _html += '</div>';
                _html += '</div>';

                return _html;
            }
        },
        cc: {
            field: {
                key: -1,
                type: 'cc',
                name: '抄送人',
                content: '请设置抄送人',
            }
            , render: function (json) {
                var _html = '';

                _html += '<div class="node-cell node-item node-wrap" data-key="{0}">'.format(json.key);

                _html += '<div class="node-box node-wrap-box start-node">';

                _html += '<div class="title" style="background: rgb(50, 150, 250);">';
                _html += '<span>{0}</span>'.format(json.name);
                _html += '<i class="btnRemove" title="删除">X</i>';
                _html += '</div>';
                _html += '<div>';
                _html += '<span>{0}</span>'.format(json.content);
                _html += '<i>&gt;</i>';
                _html += '</div>';
                _html += '</div>';
                _html += '<div class="node-add-btn-box">';
                _html += '<div class="add-node-btn">';
                _html += '<button class="addNodeClick">+</button>';
                _html += '</div>';
                _html += '</div>';
                _html += '</div>';

                return _html;
            }
        },
        branch: {
            field: {
                key: -1,
                type: 'branch',
                name: '分支',
            }
            , render: function (json) {
                var _html = '';

                _html += '<div class="node-item branch-wrap" data-key="{0}">'.format(json.key);
                _html += '<div class="branch-box-wrap">';
                _html += '<div class="branch-box">';
                _html += '<span class="add-branch" title="添加条件">添加条件</span>';
                _html += '{0}';
                _html += '</div>';
                _html += '<div class="node-add-btn-box">';
                _html += '<div class="add-node-btn">';
                _html += '<button class="addNodeClick">+</button>';
                _html += '</div>';
                _html += '</div>';
                _html += '</div>';
                _html += '</div>';

                return _html;
            }
        },
        condition: {
            field: {
                key: -1,
                type: 'condition',
                name: '条件',
                content: '请设置条件',
                level: '优先级',
            }
            , render: function (json) {
                var _html = '';

                _html += '<div class="node-cell col-box">';
                _html += '<div class="node-item condition-node" data-key="{0}">'.format(json.key);
                _html += '<div class="condition-node-box">';
                _html += '<div class="node-box auto-judge">';
                _html += '<div class="title-wrapper">';
                _html += '<span class="condition-name">{0}</span>'.format(json.name);
                _html += '<span class="condition-level">{0}</span>'.format(json.level);
                _html += '<i class="btnCopy" title="复制">C</i>';
                _html += '<i class="btnRemove" title="删除">X</i>';
                _html += '</div>';
                _html += '<div>{0}</div>'.format(json.content);
                _html += '</div>';
                _html += '<div class="node-add-btn-box">';
                _html += '<div class="add-node-btn">';
                _html += '<button class="addNodeClick">+</button>';
                _html += '</div>';
                _html += '</div>';
                _html += '</div>';
                _html += '</div>';
                _html += '</div>';

                return _html;
            }
        },
        end: {
            field: {
                key: -1,
                type: 'end',
                name: '结束流程',
            }
            , render: function (json) {
                var _html = '';

                _html += '<div class="node-cell node-item end-node" data-key="{0}">'.format(json.key);

                _html += '<div class="end-node-circle"></div>';

                _html += '<div class="end-node-text">{0}</div>'.format(json.name);

                _html += '</div>';

                return _html;
            }
        },
    };

    //渲染视图
    Class.prototype.render = function () {
        var that = this
            , options = that.config;

        if (!options.elem) {
            return;
        }

        //设置组件key值初始值
        that.config.key = 3;

        //组件渲染数组
        that.config.render = [];

        //渲染流程视图
        this.renderWorkFlow();
    };

    //渲染流程视图
    Class.prototype.renderWorkFlow = function () {
        var that = this
            , options = that.config;

        //清空
        $(options.elem).empty();

        //渲染组件
        that.renderComponent();

        //刷新分支
        that.refreshBranch();

        //绑定事件
        that.bindEvent();
    };

    //渲染组件
    Class.prototype.renderComponent = function () {
        var that = this
            , options = that.config
            , lineObj = options.line;

        for (var index in lineObj) {
            that.renderItem(index);

            that.config.key = that.config.key > index ? that.config.key : parseInt(index) + 1;
        }
    };

    //渲染组件
    Class.prototype.renderItem = function (index) {
        var that = this
            , options = that.config
            , dataObj = options.data;

        var html = that.components[dataObj[index]['type']].render(dataObj[index]).format('');
        that.appendHtml(index, html);
    };

    //刷新分支
    Class.prototype.refreshBranch = function () {
        var that = this
            , options = that.config;

        $(options.elem).find('.top-left-cover-line,.bottom-left-cover-line,.top-right-cover-line,.bottom-right-cover-line').remove();

        var branchBoxs = $(options.elem).find('.branch-box');

        $.each(branchBoxs, function (index, item) {
            var colBoxs = $(item).children(".col-box");
            colBoxs.first().append(CONDITIONFIRST);
            colBoxs.last().append(CONDITIONLAST);
        });
    };

    //挂载html
    Class.prototype.appendHtml = function (index, html) {
        var that = this
            , options = that.config
            , dataObj = options.data
            , lineObj = options.line;

        if (!that.renderCheck(index)) {
            if (lineObj[index]['prev']) {
                var prev = lineObj[index]['prev'];
                that.renderPrev(prev);

                if (!that.renderCheck(index)) {
                    var prevClass = '.node-item[data-key="' + prev + '"]';
                    if (dataObj[index]['type'] == 'condition') {
                        $(prevClass).find('.branch-box').append(html);
                    } else {
                        $(prevClass).after(html);
                    }
                    that.renderArr(index);
                }
            } else {
                $(options.elem).append(html);
                that.renderArr(index);
            }
        }
    };

    //渲染组件
    Class.prototype.renderPrev = function (index) {
        var that = this
            , options = that.config
            , dataObj = options.data
            , lineObj = options.line;

        var prevClass = '.node-item[data-key="' + index + '"]';
        if ($(prevClass).length == 0) {
            var prev = lineObj[index]['prev'];
            that.renderPrev(prev);

            if (!that.renderCheck(index)) {
                var parentClass = '.node-item[data-key="' + prev + '"]';
                var html = that.components[dataObj[index]['type']].render(dataObj[index]).format('');
                if (dataObj[index]['type'] == 'condition') {
                    $(parentClass).find('.branch-box').append(html);
                } else {
                    $(parentClass).after(html);
                }
                that.renderArr(index);
            }
        }
    };

    //已渲染数组
    Class.prototype.renderArr = function (index) {
        this.config.render.push(index.toString());
    };

    //检查是否已渲染
    Class.prototype.renderCheck = function (index) {
        if (this.config.render.indexOf(index) < 0) {
            return false;
        } else {
            return true;
        }
    };

    //绑定事件
    Class.prototype.bindEvent = function () {
        var that = this
            , options = that.config;

        //加号
        $(document).on('click', function (e) {
            e = e || window.event; //浏览器兼容性
            var elem = e.target;

            if ($(elem).hasClass('addNodeClick')) {
                $("#addtooltip-warpper").remove();
                var parent = $(elem).parents('.node-item').eq(0);
                $(TOOLTIP).appendTo(parent);
                $("#addtooltip-warpper").css({
                    "left": parent.width() / 2 + 28 + 'px',
                    "bottom": '-30px',
                }).hide().show(150);
            } else {
                $("#addtooltip-warpper").remove();
            }
        });

        //新增
        $(document).on("click", ".item-wrapper", function (e) {
            e.stopPropagation();//阻止事件冒泡
            var position = that.elemKeyPosition(this);
            var addType = $(this).data("addtype");
            var html = '';
            switch (addType) {
                case 'verify': //审核人
                case 'cc': //抄送人
                    that.addData(addType, position.current, position.next);
                    html = that.components[addType].render(that.config.data[that.config.key - 1]);
                    break;
                case 'branch': //条件分支
                    var branchNext = position.next;
                    that.addData(addType, position.current, position.next);
                    var branchKey = that.config.key - 1;
                    var branch = that.components[addType].render(that.config.data[branchKey]);
                    var condition = '';
                    for (var i = 0; i < 2; i++) {
                        that.addData('condition', branchKey, branchNext);
                        condition += that.components.condition.render(that.config.data[that.config.key - 1]);

                        if (that.config.line[branchKey]['branch'] == undefined) {
                            that.config.line[branchKey]['branch'] = [];
                        }
                        that.config.line[branchKey]['branch'].push(that.config.key - 1);
                    }
                    html = branch.format(condition);
                    break;
            }
            $(html).insertAfter($(this).parents('.node-item').eq(0));
            $("#addtooltip-warpper").hide(100);
            that.refreshBranch();
            that.change();
        });

        //删除
        $(document).on("click", ".btnRemove", function (e) {
            e.stopPropagation();//阻止事件冒泡
            var position = that.elemKeyPosition(this);
            var elem = null;
            var nodeCell = null;
            var nodeItems = null;
            var cellKey = 0;

            if ($(this).parent().hasClass('title-wrapper')) {
                elem = $(this).parents('.branch-box').eq(0);
            }

            if (elem) {
                if (elem.find('.col-box').length <= 2) {
                    nodeCell = elem.parents('.node-item').eq(0);
                    nodeItems = elem.find('.node-item');

                    $.each(nodeItems, function (index, item) {
                        var itemKey = $(item).data('key');
                        delete that.config.data[itemKey];
                        delete that.config.line[itemKey];

                        var itemClass = '.node-item[data-key="' + itemKey + '"]';
                        $(itemClass).remove();
                    });

                    cellKey = nodeCell.data('key');

                    that.config.line[that.config.line[cellKey]['prev']]['next'] = that.config.line[cellKey]['next'];
                    that.config.line[that.config.line[cellKey]['next']]['prev'] = that.config.line[cellKey]['prev'];
                    delete that.config.data[cellKey];
                    delete that.config.line[cellKey];

                    nodeCell.remove();
                } else {
                    nodeCell = $(this).parents('.node-cell').eq(0);
                    nodeItems = nodeCell.find('.node-item');

                    $.each(nodeItems, function (index, item) {
                        var itemKey = $(item).data('key');
                        delete that.config.data[itemKey];
                        delete that.config.line[itemKey];

                        var itemClass = '.node-item[data-key="' + itemKey + '"]';
                        $(itemClass).remove();
                    });

                    delete that.config.data[position.current];
                    delete that.config.line[position.current];
                    that.config.line[position.prev]['branch'].remove(position.current);

                    nodeCell.remove();
                    that.refreshBranch();
                }
            } else {
                that.config.line[position.prev]['next'] = position.next;
                that.config.line[position.next]['prev'] = position.prev;
                delete that.config.data[position.current];
                delete that.config.line[position.current];

                $(this).parents('.node-cell').eq(0).remove();
            }
            that.change();
        });

        //添加条件
        $(document).on("click", ".add-branch", function (e) {
            e.stopPropagation();//阻止事件冒泡
            var position = that.elemKeyPosition(this);

            //数据
            var data = $.extend({}, that.components['condition'].field);
            data.key = that.config.key;
            that.config.data[that.config.key] = data;

            //连线
            that.config.line[that.config.key] = {
                prev: position.current,
                current: that.config.key,
                next: position.next,
            };

            that.config.key++;

            that.config.line[position.current]['branch'].push(that.config.key - 1);
            var html = that.components.condition.render(that.config.data[that.config.key - 1]);
            $(this).parent().append(html);
            that.refreshBranch();
            that.change();
        });

        //复制条件
        $(document).on("click", ".btnCopy", function (e) {
            e.stopPropagation();//阻止事件冒泡
            var elem = $(this).parents('.col-box').eq(0);
            var nodeItems = elem.find('.node-item');
            var oldKeyArr = [];
            var newKeyArr = [];
            var branchObj = {};
            var conditionKey = 0;

            $(elem).after($(elem).clone(true, true));
            that.refreshBranch();

            $.each(nodeItems, function (index, item) {
                var oldKey = $(item).data('key');
                var newKey = that.config.key;

                var itemClass = '.node-item[data-key="' + oldKey + '"]';
                $(itemClass).eq(1).data('key', newKey);

                var oldData = that.config.data[oldKey];
                var newData = $.extend({}, oldData);
                newData['key'] = newKey;
                that.config.data[newKey] = newData;

                var oldLine = that.config.line[oldKey];
                var newLine = $.extend({}, oldLine);
                newLine['current'] = newKey;
                that.config.line[newKey] = newLine;

                if (newData['type'] == 'branch') {
                    branchObj[newKey] = newLine;
                }

                that.config.key++;

                oldKeyArr.push(oldKey);
                newKeyArr.push(newKey);

                if (index == 0) {
                    conditionKey = newKey;
                }
            });

            for (var index in branchObj) {
                var oldBranchArr = branchObj[index]['branch'];
                var newBranchArr = [];

                for (var i = 0; i < oldBranchArr.length; i++) {
                    newBranchArr.push(newKeyArr[oldKeyArr.indexOf(oldKeyArr[i])]);
                }

                that.config.line[index]['branch'] = newBranchArr;
            }

            for (var i = 0; i < newKeyArr.length; i++) {
                var prev = that.config.line[newKeyArr[i]]['prev'];
                var prevIndex = oldKeyArr.indexOf(prev);

                if (prevIndex >= 0) {
                    that.config.line[newKeyArr[i]]['prev'] = newKeyArr[prevIndex];
                }

                var next = that.config.line[newKeyArr[i]]['next'];
                var nextIndex = oldKeyArr.indexOf(next);

                if (nextIndex >= 0) {
                    that.config.line[newKeyArr[i]]['next'] = newKeyArr[nextIndex];
                }
            }

            var parentKey = elem.parents('.node-item').eq(0).data('key');
            that.config.line[parentKey]['branch'].push(conditionKey);
            that.change();
        });

        //触发节点
        $(document).on('click', '.node-box', function (e) {
            e.stopPropagation();
            var key = $(this).parents('.node-item').data('key');
            that.click(key);
        });
    };

    //元素key值定位
    Class.prototype.elemKeyPosition = function (elem) {
        var currItem = $(elem).parents('.node-item').eq(0);
        var current = currItem.data('key');

        return this.config.line[current];
    };

    //添加数据
    Class.prototype.addData = function (type, prev, next) {
        var that = this;

        //数据
        var data = $.extend({}, that.components[type].field);
        data.key = that.config.key;
        that.config.data[that.config.key] = data;

        //连线
        that.config.line[that.config.key] = {
            prev: prev,
            current: that.config.key,
            next: next,
        };

        var prevClass = '.node-item[data-key="' + prev + '"]';
        var prevObj = $(prevClass);
        var isBranchWrap = prevObj.hasClass('branch-wrap');
        var prevParentObj = prevObj.parent();
        var isColBox = prevParentObj.hasClass('col-box');
        var lastKey = 0;

        //分支
        if (isBranchWrap) {
            that.config.line[prev]['next'] = that.config.key;

            //所有分支的最后一个组件
            var colBoxs = prevObj.find('.col-box');
            $.each(colBoxs, function (index, item) {
                lastKey = $(item).children('.node-item').last().data('key');
                that.config.line[lastKey]['next'] = that.config.key;
            })
        }

        //条件
        if (isColBox) {
            that.config.line[prev]['next'] = that.config.key;

            lastKey = prevParentObj.children('.node-item').last().data('key');

            if (prev != lastKey) {
                that.config.line[next]['prev'] = that.config.key;
            }
        }

        if (!isBranchWrap && !isColBox && type != 'condition') {
            that.config.line[prev]['next'] = that.config.key;
            that.config.line[next]['prev'] = that.config.key;
        }

        that.config.key++;
    };

    //更新数据
    Class.prototype.updateData = function (key, data) {
        var that = this;

        //数据
        that.config.data[key] = $.extend(that.config.data[key], data);
    };

    //重载
    Class.prototype.reload = function () {
        this.render();
    };

    //节点点击回调
    Class.prototype.click = function (key) {
        var that = this
            , options = that.config;

        if (typeof options.click == 'function') {
            options.click(key, options.data, options.line);
        }
    };

    //节点改变回调
    Class.prototype.change = function () {
        var that = this
            , options = that.config;

        if (typeof options.change == 'function') {
            options.change(options.data, options.line);
        }
    };

    //实例
    win.workflow = {
        //渲染操作视图
        render: function (options) {
            var that = new Class(options);
            that.render();
            return that;
        }
    };
})(window, jQuery);